home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / Popup.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  23.4 KB  |  757 lines  |  [TEXT/CWIE]

  1. // Popup.java
  2. // By Ned Etcode
  3. // Copyright 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import netscape.util.*;
  8.  
  9. // ALERT! List:
  10. // Center item in display.
  11. // get background color from the list.
  12. // get rid of sizeToMinSize on list.
  13. // call setRowHeight directly based on the size of the button.
  14. // keep it from tracking the mouse outside the popup.
  15. // make the list send an action on all mouse ups.
  16. // implement Codable APIs
  17. // jla - rules for sending item's command vs. popup's command aren't clear
  18.  
  19. /** View subclass that, when clicked, pops up a window containing a ListView
  20.   * of PopupItems.  When the user selects a PopupItem, the Popup sends the
  21.   * PopupItem's command to the Popup's target.  By default, the Popup creates
  22.   * and displays PopupItems, but you can create and use your own ListItem
  23.   * subclass.
  24.   * @see PopupItem
  25.   * @see ListView
  26.   * @note 1.0 support for Keyboard UI
  27.   * @note 1.0 added enable/disable support, archiving change
  28.   * @note 1.0 updated minSize to do the right thing
  29.   * @note 1.0 new method removeItemAt() taking an index
  30.   * @note 1.0 setPopupWindow() now adds ContainerView to window
  31.   * @note 1.0 Added FormElement interface for browser needs
  32.   */
  33.  
  34. public class Popup extends View implements Target, FormElement {
  35.     ListView popupList;
  36.     Window popupWindow;
  37.     ContainerView container;
  38.     ListItem selectedItem,wasSelectedItem;
  39.     Target target;
  40.     Image image;
  41.     boolean _showingPopupForKeyboard;
  42.     boolean enabled = true;
  43.  
  44.     final static String         LISTVIEW_KEY = "popupList",
  45.                                 WINDOW_KEY = "popupWindow",
  46.                                 CONTAINER_KEY = "container",
  47.                                 SELECTEDITEM_KEY = "selectedItem",
  48.                                 TARGET_KEY = "target",
  49.                                 SELECTEDIMAGE_KEY = "selectedImage",
  50.                                 ENABLED_KEY = "enabled";
  51.  
  52.     /** Cause the popup to select the next available item.
  53.       *
  54.       */
  55.     public final static String  SELECT_NEXT_ITEM = ListView.SELECT_NEXT_ITEM;
  56.  
  57.     /** Cause the popup to select the previous available item.
  58.       *
  59.       */
  60.     public final static String  SELECT_PREVIOUS_ITEM = ListView.SELECT_PREVIOUS_ITEM;
  61.  
  62.     /** Cause the popup to popup, displaying all the available choices.
  63.       *
  64.       */
  65.     public final static String  POPUP = "popup";
  66.  
  67.     /** Cause the popup to close and cancel any changes
  68.       *
  69.       */
  70.     final static String CLOSE_POPUP_AND_CANCEL = "cancel";
  71.  
  72.     /** Cause the popup to close, commit and send command
  73.       *
  74.       */
  75.     final static String CLOSE_POPUP_AND_COMMIT = "commit";
  76.  
  77.     /** Constructs an empty Popup.
  78.       */
  79.     public Popup() {
  80.         this(0, 0, 0, 0);
  81.     }
  82.  
  83.     /** Constructs an empty Popup with bounds <B>rect</B>.  This Rect
  84.       * defines the bounds of the inactive (not popped-up) Popup. When active,
  85.       * the Popup grows vertically to fully display its items.
  86.       */
  87.     public Popup(Rect rect) {
  88.         this(rect.x, rect.y, rect.width, rect.height);
  89.     }
  90.  
  91.     /** Constructs an empty Popup with the given bounds.  This rectangle
  92.       * defines the bounds of the inactive (not popped-up) Popup. When active,
  93.       * the Popup grows vertically to fully display its items.
  94.       */
  95.     public Popup(int x, int y, int width, int height) {
  96.         super(x, y, width, height);
  97.  
  98.         ListView list;
  99.         Window window;
  100.         PopupItem prototype;
  101.  
  102.         if (false) {
  103.             window = new ExternalWindow(Window.BLANK_TYPE);
  104.         } else {
  105.             InternalWindow internalWindow =
  106.                            new InternalWindow(x, y, width, height);
  107.             internalWindow.setType(InternalWindow.BLANK_TYPE);
  108.             internalWindow.setLayer(InternalWindow.POPUP_LAYER);
  109.             internalWindow._contentView.setTransparent(true);
  110.             internalWindow.setScrollsToVisible(true);
  111.             window = internalWindow;
  112.         }
  113.  
  114.         container = new ContainerView(0, 0, width, height);
  115.         container.setTransparent(true);
  116.         container.setBorder(BezelBorder.raisedBezel());
  117.         container.setVertResizeInstruction(HEIGHT_CAN_CHANGE);
  118.         container.setHorizResizeInstruction(WIDTH_CAN_CHANGE);
  119.  
  120.         list = new ListView(0, 0, width, height);
  121.         //window.addSubview(container);
  122.  
  123.         prototype = new PopupItem();
  124.         prototype.setPopup(this);
  125.  
  126.         setPopupList(list);
  127.         setPrototypeItem(prototype);
  128.         setPopupWindow(window);
  129.         setPopupImage(Bitmap.bitmapNamed(
  130.                                     "netscape/application/PopupKnobH.gif"));
  131.         _setupKeyboard();
  132.     }
  133.  
  134.     /** Sets the prototype ListItem used by the Popup's ListView.
  135.       */
  136.     public void setPrototypeItem(ListItem item) {
  137.         popupList.setPrototypeItem(item);
  138.         if (item instanceof PopupItem) {
  139.             ((PopupItem)item).setPopup(this);
  140.         }
  141.     }
  142.  
  143.     /** Returns the prototype ListItem used by the Popup's ListView.
  144.       * @see ListView#setPrototypeItem
  145.       */
  146.     public ListItem prototypeItem() {
  147.         return popupList.prototypeItem();
  148.     }
  149.  
  150.     /** Removes all ListItems from the Popup.
  151.       */
  152.     public void removeAllItems() {
  153.         popupList.removeAllItems();
  154.     }
  155.  
  156.     /** Adds a ListItem with the given title and command to the Popup. Calls
  157.       * <b>addItem()</b> on the Popup's ListView.
  158.       * @see ListView#addItem
  159.       */
  160.     public ListItem addItem(String title, String command) {
  161.         ListItem item;
  162.  
  163.         hidePopupIfNeeded();
  164.  
  165.         item = popupList.addItem();
  166.         item.setTitle(title);
  167.         item.setCommand(command);
  168.  
  169.         return item;
  170.     }
  171.  
  172.     /** Removes the ListItem with title <b>title</b> from the Popup.
  173.       */
  174.     public void removeItem(String title) {
  175.         ListItem    nextItem;
  176.         int     i;
  177.  
  178.         if (title == null) {
  179.             return;
  180.         }
  181.  
  182.         i = popupList.count();
  183.         while (i-- > 0) {
  184.             nextItem = (ListItem)itemAt(i);
  185.             if (title.equals(nextItem.title())) {
  186.                 hidePopupIfNeeded();
  187.                 popupList.removeItemAt(i);
  188.                 return;
  189.             }
  190.         }
  191.     }
  192.  
  193.     /** Removes the ListItem at <b>index</b>.
  194.       *
  195.       */
  196.     public void removeItemAt(int index) {
  197.         if (popupList.count() > index)  {
  198.             hidePopupIfNeeded();
  199.             popupList.removeItemAt(index);
  200.         }
  201.     }
  202.  
  203.     /** Returns the index of the Popup's selected row.
  204.       */
  205.     public int selectedIndex() {
  206.         int index;
  207.  
  208.         index = popupList.indexOfItem(selectedItem);
  209.         if (index < 0 && popupList.count() > 0) {
  210.             index = 0;
  211.             selectItemAt(0);
  212.         }
  213.  
  214.         return index;
  215.     }
  216.  
  217.     /** Returns the Popup's selected ListItem.
  218.       */
  219.     public ListItem selectedItem() {
  220.         int index;
  221.  
  222.         index = selectedIndex();
  223.         if (index < 0)
  224.             return null;
  225.  
  226.         return popupList.itemAt(index);
  227.     }
  228.  
  229.     /** Selects a particular Popup item. When inactive, the Popup displays
  230.       * the currently selected ListItem.
  231.       */
  232.     public void selectItem(ListItem item) {
  233.         selectedItem = item;
  234.         draw();
  235.     }
  236.  
  237.     /** Calls <b>selectItem()</b> using the ListItem at the given row.
  238.       */
  239.     public void selectItemAt(int index) {
  240.         selectItem(popupList.itemAt(index));
  241.     }
  242.  
  243.     /** Returns the number of ListItems the Popup contains.
  244.       */
  245.     public int count() {
  246.         return popupList.count();
  247.     }
  248.  
  249.     /** Returns the ListItem at the given row index.
  250.       */
  251.     public ListItem itemAt(int index) {
  252.         return popupList.itemAt(index);
  253.     }
  254.  
  255.     /** Sets the Popup's Border. The Popup draws this Border around its
  256.       * smaller inactive state and around its window when active.  You can
  257.       * customize a Popup's look by setting a different Border.
  258.       */
  259.     public void setBorder(Border aBorder) {
  260.         container.setBorder(aBorder);
  261.     }
  262.  
  263.     /** Returns the Popup's border.
  264.       * @see #setBorder
  265.       */
  266.     public Border border() {
  267.         return container.border();
  268.     }
  269.  
  270.     /** Sets the ListView the Popup should use to maintain its ListItems.
  271.       * You can customize a Popup's look by providing a custom ListView.
  272.       */
  273.     public void setPopupList(ListView list) {
  274.         popupList = list;
  275.         popupList.setTarget(this);
  276.         popupList.setAllowsMultipleSelection(false);
  277.         popupList.setAllowsEmptySelection(true);
  278.         popupList.setTracksMouseOutsideBounds(false);
  279.         container.addSubview(popupList);
  280.     }
  281.  
  282.     /** Returns the Popup's ListView.
  283.       * @see #setPopupList
  284.       */
  285.     public ListView popupList() {
  286.         return popupList;
  287.     }
  288.  
  289.     /** Sets the Window used to contain the active Popup. You can change the
  290.       * active Popup's appearance by providing a custom Window.
  291.       */
  292.     public void setPopupWindow(Window window) {
  293.         InternalWindow  internalWindow;
  294.  
  295.         popupWindow = window;
  296.         if (window instanceof InternalWindow) {
  297.             internalWindow = (InternalWindow)window;
  298.             internalWindow.setScrollsToVisible(true);
  299.             window.addSubview(container);
  300.         }
  301.     }
  302.  
  303.     /** Returns the active Popup's Window.
  304.       * @see #setPopupWindow
  305.       */
  306.     public Window popupWindow() {
  307.         return popupWindow;
  308.     }
  309.  
  310.     /** Sets the Image displayed by the selected ListItem.
  311.       */
  312.     public void setPopupImage(Image anImage) {
  313.         image = anImage;
  314.     }
  315.  
  316.     /** Returns the Image displayed by the selected ListItem.
  317.       * @see #setPopupImage
  318.       */
  319.     public Image popupImage() {
  320.         return image;
  321.     }
  322.  
  323.     /** Sizes and positions the Popup's Window to accomodate its ListItems, and
  324.       * positions the Popup's ListView within its Window.  Popup calls this
  325.       * method before bringing its Window onscreen.
  326.       */
  327.     protected void layoutPopupWindow() {
  328.         Border  border;
  329.         Rect    windowRect;
  330.         int     selectedIndex;
  331.  
  332.         // Need to handle 0 height!  ALERT!
  333.         // popupList.sizeToMinSize();  ALERT!
  334.  
  335.         border = container.border();
  336.  
  337.         popupList.setRowHeight(bounds.height - border.heightMargin());
  338.         popupList.setBounds(border.leftMargin(),
  339.                             border.topMargin(),
  340.                             bounds.width - border.widthMargin(),
  341.                             popupList.rowHeight() * popupList.count());
  342.  
  343.         selectedIndex = selectedIndex();
  344.  
  345.         windowRect = Rect.newRect(0, 0, width(), height());
  346.         convertRectToView(null, windowRect, windowRect);
  347.  
  348.         if (rootView().windowClipView() != null) {
  349.             rootView().convertRectToView(rootView().windowClipView(),
  350.                                          windowRect, windowRect);
  351.         }
  352.  
  353.         popupWindow.setBounds(windowRect.x,
  354.                               windowRect.y
  355.                                   - selectedIndex * popupList.rowHeight(),
  356.                               popupList.width() + border.widthMargin(),
  357.                               popupList.height() + border.heightMargin());
  358.  
  359.         Rect.returnRect(windowRect);
  360.     }
  361.  
  362.     /** Brings the Popup's Window onscreen. Popup calls this method after
  363.       * calling <b>layoutPopupWindow()</b>, in response to a mouse down event
  364.       * on the Popup's inactive state. This method actually pops up the Popup.
  365.       */
  366.     protected void showPopupWindow(MouseEvent event) {
  367.         InternalWindow  internalWindow;
  368.         ExternalWindow  externalWindow;
  369.  
  370.         if (popupWindow instanceof InternalWindow) {
  371.             internalWindow = (InternalWindow)popupWindow;
  372.  
  373.             internalWindow.setRootView(rootView());
  374.             Application.application().beginModalSessionForView(internalWindow);
  375.         } else {
  376.             externalWindow = (ExternalWindow)popupWindow;
  377.  
  378.             Application.application().beginModalSessionForView(
  379.                                                 externalWindow.rootView());
  380.         }
  381.  
  382.         popupWindow.show();
  383.         rootView().setMouseView(popupList);  // ALERT!
  384.  
  385.         // Should this dispatch through the queue ALERT!
  386.         if(event != null)
  387.             popupList.mouseDown(convertEventToView(popupList, event));
  388.         else {
  389.             popupList.selectItem(selectedItem());
  390.             rootView().makeSelectedView(popupList);
  391.         }
  392.     }
  393.  
  394.     /** Catches mouse events on the Popup's inactive "button". Calls
  395.       * <b>layoutPopupWindow()</b> followed by <b>showPopupWindow()</b>.
  396.       */
  397.     public boolean mouseDown(MouseEvent event) {
  398.         if (!isEnabled()) {
  399.             return false;
  400.         }
  401.  
  402.         layoutPopupWindow();
  403.         showPopupWindow(event);
  404.  
  405.         return true;
  406.     }
  407.  
  408.     /** Enables or disables the Popup.
  409.       *
  410.       */
  411.     public void setEnabled(boolean flag) {
  412.         enabled = flag;
  413.         setDirty(true);
  414.     }
  415.  
  416.     /** Returns true if the Popup is enabled, false otherwise.
  417.       *
  418.       */
  419.     public boolean isEnabled() {
  420.         return enabled;
  421.     }
  422.  
  423.     /** Returns <b>true</b> if the Popup is transparent.  A Popup is
  424.       * transparent if its ListView is transparent.
  425.       * @see #popupList
  426.       */
  427.     public boolean isTransparent() {
  428.         return popupList.isTransparent();
  429.     }
  430.  
  431.     /** Draws the inactive Popup.
  432.       */
  433.     public void drawView(Graphics g) {
  434.         Border  border;
  435.         Rect    itemRect;
  436.         Color   color = null;
  437.  
  438.         border = container.border();
  439.  
  440.         if (selectedItem == null && popupList.selectedItem() == null) {
  441.             selectItem(popupList.itemAt(0));
  442.         }
  443.  
  444.         if (!popupList.isTransparent() && selectedItem != null &&
  445.             selectedItem.isTransparent()) {
  446.             g.setColor(popupList.backgroundColor());
  447.             g.fillRect(0, 0, width(), height());
  448.         }
  449.  
  450.         if (selectedItem != null) {
  451.             itemRect = Rect.newRect(border.leftMargin(),
  452.                                     border.topMargin(),
  453.                                     bounds.width - border.widthMargin(),
  454.                                     bounds.height - border.heightMargin());
  455.             g.pushState();
  456.             g.setClipRect(itemRect);
  457.             if (!isEnabled()) {
  458.                 color = selectedItem.textColor();
  459.                 selectedItem.setTextColor(Color.gray);
  460.             }
  461.             selectedItem.drawInRect(g, itemRect);
  462.             if (!isEnabled()) {
  463.                 selectedItem.setTextColor(color);
  464.             }
  465.             g.popState();
  466.  
  467.             Rect.returnRect(itemRect);
  468.         }
  469.  
  470.         border.drawInRect(g, 0, 0, width(), height());
  471.     }
  472.  
  473.     /** Sets the Popup's Target. The Popup sends its command to its Target when
  474.       * the currently selected ListItem changes.
  475.       */
  476.     public void setTarget(Target newTarget) {
  477.         target = newTarget;
  478.     }
  479.  
  480.     /** Returns the Popup's Target.
  481.       * @see #setTarget
  482.       */
  483.     public Target target() {
  484.         return target;
  485.     }
  486.  
  487.     /** Sets the Popup's command. The Popup sends this command to its Target
  488.       * if the selected ListItem does not have a command.
  489.       */
  490.     public void setCommand(String newCommand) {
  491.         popupList.setCommand(newCommand);
  492.     }
  493.  
  494.     /** Returns the Popup's command.
  495.       * @see #setCommand
  496.       */
  497.     public String command() {
  498.         return popupList.command();
  499.     }
  500.  
  501.     /** Sends a command to the Popup's Target.  This command is either the
  502.       * selected ListItem's command, or the Popup's command (if the ListItem
  503.       * has no command).
  504.       */
  505.     public void sendCommand() {
  506.         if (target != null) {
  507.             String realCommand = null;
  508.  
  509.             if (selectedItem != null)
  510.                 realCommand = selectedItem.command();
  511.  
  512.             if (realCommand == null)
  513.                 realCommand = command();
  514.  
  515.             target.performCommand(realCommand, this);
  516.         }
  517.     }
  518.  
  519.     /** Responds to a message from its ListView that the user has selected a
  520.       * different ListItem.  Calls <b>sendCommand()</b> and hides the
  521.       * Popup Window.
  522.       */
  523.     public void performCommand(String command, Object data) {
  524.         InternalWindow  internalWindow;
  525.         ExternalWindow  externalWindow;
  526.  
  527.         if(SELECT_NEXT_ITEM.equals(command)) {
  528.             selectNextItem(true);
  529.         } else if(SELECT_PREVIOUS_ITEM.equals(command)) {
  530.             selectNextItem(false);
  531.         } else if(POPUP.equals(command)) {
  532.             layoutPopupWindow();
  533.             wasSelectedItem = selectedItem();
  534.             _showingPopupForKeyboard = true;
  535.             showPopupWindow(null);
  536.             _setupKeyboardToClosePopup(true);
  537.         } else {
  538.             if(showingPopupForKeyboard()) {
  539.                 boolean shouldClose = false;
  540.                 if(CLOSE_POPUP_AND_CANCEL.equals(command)) {
  541.                     selectItem(wasSelectedItem);
  542.                     shouldClose = true;
  543.                 } else if(CLOSE_POPUP_AND_COMMIT.equals(command)) {
  544.                     selectItem(popupList.selectedItem());
  545.                     if(popupList.selectedItem() != null)
  546.                         sendCommand();
  547.                     shouldClose = true;
  548.                 }
  549.  
  550.                 if(shouldClose) {
  551.                     popupList.disableDrawing();
  552.                     popupList.deselectItem(popupList.selectedItem());
  553.                     popupList.reenableDrawing();
  554.                     popupWindow.hide();
  555.  
  556.                     if (popupWindow instanceof InternalWindow) {
  557.                         internalWindow = (InternalWindow)popupWindow;
  558.  
  559.                         Application.application().endModalSessionForView(internalWindow);
  560.                     } else {
  561.                         externalWindow = (ExternalWindow)popupWindow;
  562.  
  563.                         Application.application().endModalSessionForView(
  564.                                         externalWindow.rootView());
  565.                     }
  566.                     _setupKeyboardToClosePopup(false);
  567.                     _showingPopupForKeyboard = false;
  568.                 }
  569.             } else {
  570.                 if (popupList.selectedItem() != null) {
  571.                     selectedItem = popupList.selectedItem();
  572.                 }
  573.  
  574.                 if (selectedItem != null) {
  575.                     sendCommand();
  576.                 }
  577.  
  578.                 popupList.disableDrawing();
  579.                 popupList.deselectItem(selectedItem);
  580.                 popupList.reenableDrawing();
  581.                 popupWindow.hide();
  582.  
  583.                 if (popupWindow instanceof InternalWindow) {
  584.                     internalWindow = (InternalWindow)popupWindow;
  585.  
  586.                     Application.application().endModalSessionForView(internalWindow);
  587.                 } else {
  588.                     externalWindow = (ExternalWindow)popupWindow;
  589.  
  590.                     Application.application().endModalSessionForView(
  591.                                          externalWindow.rootView());
  592.                 }
  593.                 _setupKeyboardToClosePopup(false);
  594.             }
  595.         }
  596.  
  597.         draw();
  598.     }
  599.  
  600.     public Size minSize()   {
  601.         int w, h;
  602.         int bw, bh;
  603.         int iw, ih;
  604.  
  605.         bw = 0;
  606.         bh = 0;
  607.         if(container.border() != null)  {
  608.             bw = container.border().widthMargin();
  609.             bh = container.border().heightMargin();
  610.         }
  611.  
  612.         w = 0;
  613.         h = 0;
  614.         if(popupList != null)   {
  615.             w = popupList.minItemWidth();
  616.             h = popupList.minItemHeight();
  617.         }
  618.  
  619.         iw = 0;
  620.         ih = 0;
  621.         if(image != null)   {
  622.             iw = image.width();
  623.             ih = image.height();
  624.         }
  625.  
  626.         // We want the higher of the row height or the image height
  627.         // if imageHieght is less than height, we just want h, otherwise
  628.         // we need to add the difference.
  629.         if(ih < h)  {
  630.             ih = 0;
  631.         } else {
  632.             ih = h - ih;
  633.         }
  634.  
  635.         return new Size(bw + w + iw, bh + h + ih);
  636.     }
  637.  
  638.     /** Describes the Popup class' information.
  639.       * @see Codable#describeClassInfo
  640.       */
  641.     public void describeClassInfo(ClassInfo info) {
  642.         super.describeClassInfo(info);
  643.  
  644.         info.addClass("netscape.application.Popup", 2);
  645.         info.addField(LISTVIEW_KEY, OBJECT_TYPE);
  646.         info.addField(WINDOW_KEY, OBJECT_TYPE);
  647.         info.addField(CONTAINER_KEY, OBJECT_TYPE);
  648.         info.addField(SELECTEDITEM_KEY, OBJECT_TYPE);
  649.         info.addField(TARGET_KEY, OBJECT_TYPE);
  650.         info.addField(SELECTEDIMAGE_KEY, OBJECT_TYPE);
  651.  
  652.         info.addField(ENABLED_KEY, BOOLEAN_TYPE);
  653.     }
  654.  
  655.     /** Archives the Popup instance.
  656.       * @see Codable#encode
  657.       */
  658.     public void encode(Encoder encoder) throws CodingException {
  659.         super.encode(encoder);
  660.         encoder.encodeObject(LISTVIEW_KEY, popupList);
  661.         encoder.encodeObject(WINDOW_KEY, popupWindow);
  662.         encoder.encodeObject(CONTAINER_KEY, container);
  663.         encoder.encodeObject(SELECTEDITEM_KEY, selectedItem);
  664.         encoder.encodeObject(TARGET_KEY, target);
  665.         encoder.encodeObject(SELECTEDIMAGE_KEY, image);
  666.  
  667.         encoder.encodeBoolean(ENABLED_KEY, enabled);
  668.     }
  669.  
  670.     /** Unarchives the Popup instance.
  671.       * @see Codable#decode
  672.       */
  673.     public void decode(Decoder decoder) throws CodingException {
  674.         super.decode(decoder);
  675.         popupList = (ListView)decoder.decodeObject(LISTVIEW_KEY);
  676.         popupWindow = (Window)decoder.decodeObject(WINDOW_KEY);
  677.         container = (ContainerView)decoder.decodeObject(CONTAINER_KEY);
  678.         selectedItem = (ListItem)decoder.decodeObject(SELECTEDITEM_KEY);
  679.         target = (Target)decoder.decodeObject(TARGET_KEY);
  680.         image = (Image)decoder.decodeObject(SELECTEDIMAGE_KEY);
  681.  
  682.         if (decoder.versionForClassName("netscape.application.Popup") > 1) {
  683.             enabled = (boolean)decoder.decodeBoolean(ENABLED_KEY);
  684.         }
  685.     }
  686.  
  687.     void _setupKeyboard() {
  688.         removeAllCommandsForKeys();
  689.         setCommandForKey(SELECT_NEXT_ITEM,KeyEvent.DOWN_ARROW_KEY,View.WHEN_SELECTED);
  690.         setCommandForKey(SELECT_PREVIOUS_ITEM,KeyEvent.UP_ARROW_KEY,View.WHEN_SELECTED);
  691.         setCommandForKey(POPUP,KeyEvent.RETURN_KEY,View.WHEN_SELECTED);
  692.         setCommandForKey(POPUP,' ',View.WHEN_SELECTED);
  693.     }
  694.  
  695.     void selectNextItem(boolean forward) {
  696.         int index = selectedIndex();
  697.         int count = count();
  698.  
  699.         if(forward && index < (count-1))
  700.             selectItemAt(index+1);
  701.         else if(!forward && index > 0)
  702.             selectItemAt(index-1);
  703.         if(selectedItem() != null)
  704.             sendCommand();
  705.     }
  706.  
  707.  
  708.     /** Return whether this view can become the selected view
  709.       * when the user is moving from view to views with the keyboard
  710.       * Popup's implementation returns true
  711.       *
  712.       */
  713.     public boolean canBecomeSelectedView() {
  714.         return true;
  715.     }
  716.  
  717.  
  718.     void _setupKeyboardToClosePopup(boolean doIt) {
  719.         if(doIt) {
  720.             setCommandForKey(CLOSE_POPUP_AND_CANCEL,KeyEvent.ESCAPE_KEY,View.ALWAYS);
  721.             setCommandForKey(CLOSE_POPUP_AND_COMMIT,KeyEvent.RETURN_KEY,View.ALWAYS);
  722.         } else {
  723.             removeCommandForKey(KeyEvent.ESCAPE_KEY);
  724.             setCommandForKey(POPUP,KeyEvent.RETURN_KEY,View.WHEN_SELECTED);
  725.         }
  726.     }
  727.  
  728.     protected void ancestorWillRemoveFromViewHierarchy(View view)   {
  729.         super.ancestorWillRemoveFromViewHierarchy(view);
  730.         hidePopupIfNeeded();
  731.     }
  732.  
  733.     /** @private */
  734.     public void hidePopupIfNeeded() {
  735.         if(showingPopupForKeyboard()) {
  736.             performCommand(CLOSE_POPUP_AND_CANCEL, this);
  737.         }
  738.     }
  739.  
  740.     /** @private */
  741.     public boolean showingPopupForKeyboard()    {
  742.         return _showingPopupForKeyboard;
  743.     }
  744.  
  745.     /** Implementation of the FormElement interface
  746.       *
  747.       */
  748.     public String formElementText() {
  749.         if (selectedItem() != null) {
  750.             return selectedItem().title();
  751.         } else {
  752.             return "";
  753.         }
  754.     }
  755. }
  756.  
  757.